package com.moorror.codegenvel.view.window.codegenxrender.tree;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.project.Project;
import com.moorror.codegenvel.common.dialog.DialogFormTable;
import com.moorror.codegenvel.common.dialog.MRDialog;
import com.moorror.codegenvel.common.dialog.MRDialogInputName;
import com.moorror.codegenvel.common.sql.SqlTableDesc;
import com.moorror.codegenvel.common.table.TreeLineObject;
import com.moorror.codegenvel.common.tree.MTTreeCell;
import com.moorror.codegenvel.common.tree.TreePanelMark;
import com.moorror.codegenvel.common.tree.TreeRightPanelJson;
import com.moorror.codegenvel.common.tree.actions.CopyGenNewTreeAction;
import com.moorror.codegenvel.common.tree.actions.DeleteRightContentSqliteAction;
import com.moorror.codegenvel.common.tree.actions.SaveRightContentSqliteAllAction;
import com.moorror.codegenvel.common.tree.actions.codegenxrender.GenCodeXRenderAddTableAction;
import com.moorror.codegenvel.common.tree.actions.gencode.GenCodeExtractVelocityTemplateAction;
import com.moorror.codegenvel.common.tree.actions.gencode.GenCodeExtractVelocityTemplateCopyPathAction;
import com.moorror.codegenvel.common.tree.actions.gencode.GenCodeVelocityAction;
import com.moorror.codegenvel.common.tree.enums.AddSubTreeNodeType;
import com.moorror.codegenvel.common.utils.JacksonUtils;
import com.moorror.codegenvel.db.mysql.utils.HikaricpUtils;
import com.moorror.codegenvel.db.sqlite.dao.BaseDAO;
import com.moorror.codegenvel.db.sqlite.dao.impl.*;
import com.moorror.codegenvel.db.sqlite.entity.*;
import com.moorror.codegenvel.utils.GuiUtils;
import com.moorror.codegenvel.utils.MConverterUtils;
import com.moorror.codegenvel.utils.NameUtils;
import com.moorror.codegenvel.view.component.CodeGenByVelocityComponent;
import com.moorror.codegenvel.view.component.TabContentRightShow;
import com.moorror.codegenvel.view.window.codegen.CodeGenLeft;
import com.moorror.codegenvel.view.window.codegen.tree.MTTreeCellCodeGenData;
import com.moorror.codegenvel.view.window.codegen.view.CodeGenScenePanel;
import com.moorror.codegenvel.view.window.codegenxrender.domain.CodeGenXRenderConnectOtherJson;
import com.moorror.codegenvel.view.window.codegenxrender.domain.TableAddDesc;
import lombok.Getter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import java.util.*;

/**
 * @Author jiyanghuang
 * @Date 2024/4/11 23:14
 */
public class MTTreeCellCodeGenXRenderConnectName implements MTTreeCell {

    private Project project;

    private List<MTTreeCellCodeGenData> mockDatas = Lists.newArrayList();
    @Getter
    private TreeRightPanelJson treeRightPanelJson;

    @Getter
    private CodeGenScenePanel codeGenScenePanel;

    /**
     * 真实的数据对象
     */
    @Getter
    private CodeGenXRenderConnect model;

    public MTTreeCellCodeGenXRenderConnectName(Project project, CodeGenXRenderConnect model) {
        this.project = project;
        this.model = model;
    }


    @Override
    public String cellShow() {
        return model.getName();
    }

    @Override
    public Icon iconSelected() {
        return GuiUtils.SCENE;
    }

    @Override
    public Icon iconUnselected() {
        return GuiUtils.SCENE;
    }

    @Override
    public AddSubTreeNodeType addSubTreeNodeType() {
        return AddSubTreeNodeType.DIALOG;
    }

    @Override
    public DefaultMutableTreeNode buildSubTreeNode(String jsonStr, TreePanelMark treePaneLMark) {
        CodeGenTemplate codeGenTemplate = CodeGenTemplate.of(jsonStr);
        model.addChildren(codeGenTemplate);
        MTTreeCellCodeGenData mockScene = new MTTreeCellCodeGenData(project, codeGenTemplate);
        DefaultMutableTreeNode sequenceTreeNode = new DefaultMutableTreeNode(mockScene);
        return sequenceTreeNode;
    }

    @Override
    public void addSubTreeNodeDialog(JTree tree, DefaultMutableTreeNode mutabLeTreeNode, TreePanelMark treePaneLMark) {
        CodeGenLeft mockLeft = (CodeGenLeft) treePaneLMark;
        new MRDialogInputName("", "template name", mockLeft.fetchProject(), (form) -> {
            CodeGenTemplate codeGenTemplate = AbEntity.of(CodeGenTemplate.class);
            codeGenTemplate.setName(form.getInputName().getText());
            return BaseDAO.checkExistAdd(codeGenTemplate, CodeGenTemplateDaoImpl.getInstance(), CodeGenTemplate::getName, () -> {
                DefaultMutableTreeNode chiLdNode = buildSubTreeNode(form.getInputName().getText(), treePaneLMark);
                addSubTreeNode(tree, mutabLeTreeNode, treePaneLMark, chiLdNode);
                /**
                 * 添加关联关系
                 */
                CodeGenSceneTemplate codeGenSceneTemplate = AbEntity.of(CodeGenSceneTemplate.class);
                codeGenSceneTemplate.setScene(model.getName());
                codeGenSceneTemplate.setTemplate(codeGenTemplate.getName());
                CodeGenSceneTemplate ua = BaseDAO.connWrap((conn) -> {
                    return CodeGenSceneTemplateDaoImpl.getInstance().insert(conn, codeGenSceneTemplate);
                });
                if(null == ua){
                    return Pair.of(false, " add sceneTemplate fail ");
                }
                return Pair.of(true, null);
            });
        }).ofDialogShow();
    }

    @Override
    public void treeSelectionListener(JTree tree, DefaultMutableTreeNode mutableTreeNode, TreePanelMark treePanelMark) {
        try {
            if (null == treeRightPanelJson) {
                treeRightPanelJson = new TreeRightPanelJson(project, model);
            }
            TabContentRightShow tabContentRightShow = CodeGenByVelocityComponent.getInstance(project).findInstance(TabContentRightShow.class);
            tabContentRightShow.updatePanel(treeRightPanelJson);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public ActionGroup rightClickActionGroup(JTree tree, DefaultMutableTreeNode mutableTreeNode, DefaultActionGroup defaultActionGroup, TreePanelMark treePanelMark) {
        defaultActionGroup.add(new GenCodeXRenderAddTableAction(treePanelMark, "Add Table", "Add Table", this::addTable));
        defaultActionGroup.add(new GenCodeVelocityAction(treePanelMark, "Gen code velocity", "Gen code velocity"));
        defaultActionGroup.add(new SaveRightContentSqliteAllAction(treePanelMark, "saveSceneToSqlite", "save mock scene to sqlite"));
        defaultActionGroup.add(new CopyGenNewTreeAction("Copy And Generate New Scene", "Copy And Generate New Scene", treePanelMark));
        defaultActionGroup.add(new DeleteRightContentSqliteAction(treePanelMark, "deleteSceneFromSqlite", "delete mock scene from sqlite"));
        defaultActionGroup.add(new GenCodeExtractVelocityTemplateAction(treePanelMark, "Extract Template", "Extract Template"));
        defaultActionGroup.add(new GenCodeExtractVelocityTemplateCopyPathAction(treePanelMark, "Extract Template Copy Path", "Extract Template Copy Path"));
        return defaultActionGroup;
    }

    @Override
    public void genCodeVelocity(TreePanelMark treePanelMark, DefaultMutableTreeNode mutableTreeNode) {
        if (mutableTreeNode.getChildCount() >= 0) {
            List<DefaultMutableTreeNode> genList = Lists.newArrayList();
            for (Enumeration<?> e = mutableTreeNode.children(); e.hasMoreElements(); ) {
                TreeNode n = (TreeNode) e.nextElement();
                if(n instanceof DefaultMutableTreeNode){
                    DefaultMutableTreeNode sub = (DefaultMutableTreeNode)n;
                    genList.add(sub);
                }
            }
            if(CollectionUtils.isNotEmpty(genList)){
                Collections.sort(genList, new Comparator<DefaultMutableTreeNode>() {
                    @Override
                    public int compare(DefaultMutableTreeNode o1, DefaultMutableTreeNode o2) {
                        String one = orderGen(o1);
                        String two = orderGen(o2);
                        return Integer.valueOf(one) - Integer.valueOf(two);
                    }
                });
                for(DefaultMutableTreeNode treeNode : genList){
                    MTTreeCellCodeGenData mtTreeCellCodeGenData = (MTTreeCellCodeGenData)treeNode.getUserObject();
                    mtTreeCellCodeGenData.genCodeVelocity(treePanelMark, treeNode);
                }
            }
        }
    }

    @Override
    public List<MTTreeCell> subTreeCell() {
        return (List) mockDatas;
    }

    @Override
    public void saveRightContentSqlite(TreePanelMark treePanelMark) {
        try {
            /**
             * 界面没有打开，没有填充数据
             */
            if(null == treeRightPanelJson){
                return;
            }
            /**
             * 右边得有统一的 fetchValue 然后保存
             */
            String json = treeRightPanelJson.jsonValue();
            // todo 优化
            JsonNode jsonNode = JacksonUtils.toJsonNode(json);
            ObjectNode objectNode = (ObjectNode)jsonNode;
            objectNode.remove("children");
            /**
             * 更新表
             */
            BaseDAO.update(CodeGenXRenderConnectDaoImpl.getInstance(), JacksonUtils.toJavaObject(jsonNode.toString(), model.getClass()));

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


    @Override
    public void deleteRightContentFromSqlite(DefaultMutableTreeNode mutableTreeNode, TreePanelMark treePanelMark) {
        try {
//            BaseDAO.manyToManyDelete(CodeGenSceneDaoImpl.getInstance(), CodeGenSceneTemplateDaoImpl.getInstance(), CodeGenTemplateDaoImpl.getInstance(), codeGenScene, (st, t) -> {
//                CodeGenTemplate codeGenTemplate = (CodeGenTemplate) t;
//                CodeGenSceneTemplate codeGenSceneTemplate = AbEntity.of(CodeGenSceneTemplate.class);
//                codeGenSceneTemplate.setScene(st.getName());
//                codeGenSceneTemplate.setTemplate(codeGenTemplate.getName());
//                return codeGenSceneTemplate;
//            });
//            this.removeCurrent(treePanelMark.jTree(), mutableTreeNode);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void copyGenNewTree(TreePanelMark treePanelMark, DefaultMutableTreeNode mutableTreeNode) {
//        CodeGenLeft mockLeft = (CodeGenLeft) treePanelMark;
//        new MRDialogInputName("", "New Scene Name", treePanelMark.fetchProject(), (form) -> {
//            CodeGenScene codeGenSceneNew = AbEntity.of(CodeGenScene.class);
//            codeGenSceneNew.setName(form.getInputName().getText());
//            return BaseDAO.checkExistAdd(codeGenSceneNew, CodeGenSceneDaoImpl.getInstance(), CodeGenScene::getName, () -> {
//                if(CollectionUtils.isNotEmpty(codeGenScene.getChildren())){
//                    BaseDAO.copyMMN(codeGenSceneNew.getName(),CodeGenSceneTemplateDaoImpl.getInstance(), codeGenScene.getChildren(), CodeGenSceneTemplate.class, null);
//                }
//                /**
//                 * 更新树
//                 */
//                treePanelMark.treeReload(treePanelMark.rootTreeNode(), () -> {
//                    List<CodeGenScene> codeGenScenes = CodeGenSceneDaoImpl.getInstance().searchLikeMTM(codeGenSceneNew.getName());
//                    TreeCellEntityUtils.genTreeRootAppend(treePanelMark.rootTreeNode(), project, codeGenScenes);
//                });
//                return Pair.of(true, null);
//            });
//        }).ofDialogShow();
    }



    private String orderGen(DefaultMutableTreeNode sub) {
        String order = "100";
        if (sub.getUserObject() instanceof MTTreeCellCodeGenData) {
            MTTreeCellCodeGenData mtTreeCellCodeGenData = (MTTreeCellCodeGenData) sub.getUserObject();
            if (null != mtTreeCellCodeGenData && null != mtTreeCellCodeGenData.getCodeGenTemplate() && null != mtTreeCellCodeGenData.getCodeGenTemplate().getOrderGen()) {
                order = mtTreeCellCodeGenData.getCodeGenTemplate().getOrderGen();
            }
        }
        return order;
    }

    /**
     * action 转一道，然后调用
     * 添加table
     * @param mutableTreeNode
     * @param treePanelMark
     */
    public void addTable(DefaultMutableTreeNode mutableTreeNode, TreePanelMark treePanelMark){
        List<SqlTableDesc> tables = HikaricpUtils.tables(model.getUrl(), model.getUsername(), model.getPassword());
        Set<String> sets =  BaseDAO.queryNSetByM(CodeGenXRenderTableDaoImpl.getInstance(), Lists.newArrayList(String.valueOf(model.getId())), CodeGenXRenderTable::getNameTable);
        List<TableAddDesc> dataList = MConverterUtils.aToBList(tables, (sqlTableDesc -> {
            return convert(sqlTableDesc, sets);
        }));
        DialogFormTable dialogFormTable = new DialogFormTable(treePanelMark.fetchProject(), "Add Table", TableAddDesc.class, dataList, (s) -> {
//                tableDesc.setFullColumn((List)s);
            List<CodeGenXRenderTable> codeGenXRenderTables = Lists.newArrayList();
            for(TreeLineObject treeLineObject : s){
                TableAddDesc tableAddDesc = (TableAddDesc)treeLineObject;
                CodeGenXRenderTable codeGenXRenderTable = convert(tableAddDesc, model);
                if(null != codeGenXRenderTable){
                    codeGenXRenderTables.add(codeGenXRenderTable);
                }
            }
            if(CollectionUtils.isNotEmpty(codeGenXRenderTables)){
                for(CodeGenXRenderTable codeGenXRenderTable : codeGenXRenderTables){
                    CodeGenXRenderTable codeGenXRenderTableQ = BaseDAO.insert(CodeGenXRenderTableDaoImpl.getInstance(), codeGenXRenderTable);
                    List<String> sceneList = CodeGenXRenderConnectOtherJson.nameTableScene(model.getOtherConfigJson());
                    if(CollectionUtils.isNotEmpty(sceneList)){
                        for(String scene : sceneList){
                            CodeGenXRenderTableConfig tableConfig = new CodeGenXRenderTableConfig();
                            tableConfig.setKf(String.valueOf(codeGenXRenderTableQ.getId()));
                            tableConfig.setNameTableScene(scene);
                            tableConfig.setJsonTableConfig("{}");
                            BaseDAO.insert(CodeGenXRenderTableConfigDaoImpl.getInstance(), tableConfig);
                        }
                    }
                    System.out.println("GenId---------->");
                    System.out.println(JacksonUtils.toJSONString(codeGenXRenderTableQ));
                }
            }
        });
        MRDialog.of(dialogFormTable).show();
    }

    public static TableAddDesc convert(SqlTableDesc sqlTableDesc, Set<String> check){
        TableAddDesc tableAddDesc = new TableAddDesc();
        tableAddDesc.setNameTableOrig(sqlTableDesc.getNameTable());
        tableAddDesc.setNameTable(NameUtils.underScoreUpperCamel(sqlTableDesc.getNameTable()));
        if(check.contains(sqlTableDesc.getNameTable())){
            tableAddDesc.setAppended(true);
        }
        if(StringUtils.isNotBlank(sqlTableDesc.getComment()) && sqlTableDesc.getComment().contains("#end")){
            String[] splits = sqlTableDesc.getComment().split("#end");
            String[] kvPairs = splits[0].trim().split(",");
            ObjectNode objectNode = JacksonUtils.genObjectNode();
            for(String kvPair : kvPairs){
                String[] realKV = kvPair.split("=");
                objectNode.put(realKV[0], realKV[1]);
            }
            tableAddDesc.setExtColumnJson(objectNode.toString());
        }
        return tableAddDesc;
    }

    public static CodeGenXRenderTable convert(TableAddDesc tableAddDesc, CodeGenXRenderConnect codeGenXRenderConnect){
        if(!tableAddDesc.isToAppend()){
            return null;
        }
        CodeGenXRenderTable codeGenXRenderTable = new CodeGenXRenderTable();
        codeGenXRenderTable.setNameTable(tableAddDesc.getNameTableOrig());
        codeGenXRenderTable.setNameTableJava(tableAddDesc.getNameTable());
        codeGenXRenderTable.setKf(String.valueOf(codeGenXRenderConnect.getId()));
        codeGenXRenderTable.setExtColumnJson(tableAddDesc.getExtColumnJson());
        return codeGenXRenderTable;
    }
}


